/*
 * $Id: JMapFrame.java 24 2009-03-31 23:40:10Z aaron.day $
 */
package org.crazydays.gameplan.map.swing;


import java.awt.Component;
import java.awt.Dimension;
import java.awt.Point;

import javax.swing.JInternalFrame;
import javax.swing.JLayeredPane;
import javax.swing.JScrollPane;

import org.crazydays.gameplan.GamePlan;
import org.crazydays.gameplan.map.IGameMap;
import org.crazydays.gameplan.map.swing.event.MapFrameMouseAdaptor;

/**
 * JMapFrame is the implementation of an JInternalFrame to display a GameMap.
 * The frame consists of a JScrollPane which contains a JMapPane. A JMap and
 * JMapGrid is added to the JMapPane.
 */
public class JMapFrame
        extends JInternalFrame
{
	/** serial version uid */
	public final static long serialVersionUID =
	        "$Id: JMapFrame.java 24 2009-03-31 23:40:10Z aaron.day $"
	                .hashCode();

	/** game plan */
	protected GamePlan gamePlan;

	/** game map */
	protected IGameMap gameMap;

	/** scroll pane */
	protected JScrollPane scrollPane;

	/** layered pane */
	protected JMapPane mapPane;

	/** map */
	protected JMap map;

	/** map grid */
	protected JMapGrid grid;

	/** context menu */
	protected JMapContextMenu contextMenu;

	/**
	 * JMapFrame constructor.
	 * 
	 * @param gamePlan GamePlan
	 * @param gameMap Game map
	 */
	public JMapFrame(GamePlan gamePlan, IGameMap gameMap)
	{
		this(gamePlan, gameMap, new Point(0, 0));
	}

	/**
	 * JMapFrame constructor.
	 * 
	 * @param gamePlan GamePlan
	 * @param gameMap Game map
	 * @param location Location
	 */
	public JMapFrame(GamePlan gamePlan, IGameMap gameMap, Point location)
	{
		super(gameMap.getName(), true, true, true);

		setGamePlan(gamePlan);
		setGameMap(gameMap);
		setLocation(location);

		initialize();
	}

	/**
	 * Initialize map frame.
	 */
	protected void initialize()
	{
		initializeContentPane();
		initializeMap();
		initializeMapGrid();
		initializeContextMenu();

		// set visible and pack
		setVisible(true);
		pack();
	}

	/**
	 * Initialize content pane as layered pane.
	 */
	protected void initializeContentPane()
	{
		mapPane = new JMapPane();
		mapPane.setPreferredSize(getGameMapPreferredSize());
		mapPane.setVisible(true);

		scrollPane =
		        new JScrollPane(mapPane,
		                JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
		                JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);

		setContentPane(scrollPane);
	}

	/**
	 * Get game map preferred dimension.
	 * 
	 * @return Dimension
	 */
	protected Dimension getGameMapPreferredSize()
	{
		return new Dimension(gameMap.getGeometry().getWidth(), gameMap
		        .getGeometry().getHeight());
	}

	/**
	 * Initialize map layer.
	 */
	protected void initializeMap()
	{
		// create jmap
		map = new JMap(getGameMap());
		map.setVisible(true);
		mapPane.add(map, JLayeredPane.DEFAULT_LAYER);
	}

	/**
	 * Initialize map geometry layer.
	 */
	protected void initializeMapGrid()
	{
		grid = new JMapGrid(getGameMap());
		grid.setVisible(true);
		mapPane.add(grid, JLayeredPane.DRAG_LAYER - 1);
	}

	/**
	 * Initialize context menu.
	 */
	protected void initializeContextMenu()
	{
		contextMenu = new JMapContextMenu(getGamePlan(), this);
		mapPane.addMouseListener(new MapFrameMouseAdaptor(this));
	}

	/**
	 * Set game plan.
	 * 
	 * @param gamePlan GamePlan
	 */
	public void setGamePlan(GamePlan gamePlan)
	{
		this.gamePlan = gamePlan;
	}

	/**
	 * Get game plan.
	 * 
	 * @return GamePlan
	 */
	public GamePlan getGamePlan()
	{
		return gamePlan;
	}

	/**
	 * Set game map.
	 * 
	 * @param gameMap Game map
	 */
	public void setGameMap(IGameMap gameMap)
	{
		this.gameMap = gameMap;
	}

	/**
	 * Get game map.
	 * 
	 * @return Game map
	 */
	public IGameMap getGameMap()
	{
		return gameMap;
	}

	/**
	 * Set grid visible.
	 * 
	 * @param visible Visible
	 */
	public void setGridVisible(boolean visible)
	{
		grid.setVisible(visible);
	}

	/**
	 * Is grid visible.
	 * 
	 * @return Visible
	 */
	public boolean isGridVisible()
	{
		return grid.isVisible();
	}

	/**
	 * Show context menu.
	 * 
	 * @param invoker Invoker
	 * @param x X
	 * @param y Y
	 */
	public void showContextMenu(Component invoker, int x, int y)
	{
		contextMenu.show(invoker, x, y);
	}
}
